package jge.renderer.impl;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES1;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.fixedfunc.GLLightingFunc;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;

import com.jogamp.opengl.util.FPSAnimator;

import jge.datatypes.RESULT;
import jge.renderer.JGERenderDevice;
import jge.window.JGEWindow;

public class OpenGLDevice implements JGERenderDevice {
	
	private GLCanvas canvas;
	private FPSAnimator animator;
	private OpenGLDevice.OpenGLRenderer renderer;
	
	private int width;
	private int height;

	@Override
	public RESULT Init(JGEWindow window) {
		switch (window.getApiType()) {
		case AWT:
			this.InitAWT(window);
			return RESULT.OK;
			
		default:
			return RESULT.FAIL;
		}
	}

	@Override
	public void Release() {
		// TODO Implement OpenGLDevice Release method

	}

	@Override
	public boolean IsRunning() {
		// TODO Implement OpenGLDevice IsRunning method
		return false;
	}

	@Override
	public RESULT BeginRendering(boolean clearPixel, boolean clearDepth, boolean clearStencil) {
		// TODO Implement OpenGLDevice BeginRendering method
		return null;
	}

	@Override
	public void EndRendering() {
		// TODO Implement OpenGLDevice EndRendering method

	}

	@Override
	public RESULT Clear(boolean clearPixel, boolean clearDepth, boolean clearStencil) {
		// TODO Implement OpenGLDevice Clear method
		return null;
	}

	@Override
	public void SetClearColor(float red, float green, float blue) {
		// TODO Implement OpenGLDevice SetClearColor method

	}
	
	private void InitAWT(JGEWindow window) {
		GLProfile glp = GLProfile.get(GLProfile.GL2);
		GLCapabilities caps = new GLCapabilities(glp);
		caps.setDoubleBuffered(true);
		this.canvas = new GLCanvas(caps);
		
		this.width = window.getWidth();
		this.height = window.getHeight();
		
		this.renderer = new OpenGLDevice.OpenGLRenderer();
		this.canvas.addGLEventListener(this.renderer);
		
		window.add(this.canvas);
		
		this.animator = new FPSAnimator(this.canvas, 60);
		this.animator.add(this.canvas);
		
		this.animator.start();
	}
	
	private class OpenGLRenderer implements GLEventListener {
		@Override
		public void display(GLAutoDrawable drawable) {
			GL2 gl = drawable.getGL().getGL2();
			gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
			
			gl.glTranslatef(0, 0, -2);
			gl.glBegin(GL.GL_TRIANGLES);
			gl.glColor3f(1f, 0, 0); gl.glVertex3d(0, 0, 0);
			gl.glColor3f(0, 0, 1f); gl.glVertex3d(1, 0, 0);
			gl.glColor3f(0, 1f, 0); gl.glVertex3d(0, 1, 0);
			gl.glEnd();
			gl.glTranslatef(0, 0, 2);
			
			gl.glFlush();
		}

		@Override
		public void dispose(GLAutoDrawable drawable) {

		}

		@Override
		public void init(GLAutoDrawable drawable) {
			GL2 gl = drawable.getGL().getGL2();
			GLU glu = new GLU();
			
			gl.glClearColor(0, 0, 0, 0);
			gl.glClearDepth(1.0f);
			gl.glDepthFunc(GL.GL_LEQUAL);
			gl.glEnable(GL.GL_DEPTH_TEST);
			gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
			gl.glFrontFace(GL.GL_CCW);
			gl.glEnable(GL.GL_CULL_FACE);
			gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
			gl.glPolygonMode(GL.GL_BACK, GL2GL3.GL_LINE);
			gl.glEnable(GL.GL_TEXTURE_2D);
			
			gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
			gl.glLoadIdentity();
			glu.gluPerspective(60.0, (double) OpenGLDevice.this.width / (double) OpenGLDevice.this.height, 0.1, 100000.0);
			gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
		}

		@Override
		public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
			GL2 gl = drawable.getGL().getGL2();
			GLU glu = new GLU();
			
			OpenGLDevice.this.width = width;
			OpenGLDevice.this.height = height;
			
			gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
			gl.glLoadIdentity();
			glu.gluPerspective(60.0, (double) OpenGLDevice.this.width / (double) OpenGLDevice.this.height, 0.1, 100000.0);
			gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
		}	
	}

}
